
class Form < FieldComposite
  #Handler.enable self
  attr_accessor :app, :page, :fields, :success, :request, :env, :e

  def initialize
    super
    self.form = self
    init_element Element.new(:form, :method => 'post')
    self << InputHidden.new(:name => 'a', :value => self.class.to_s)
  end

  def recieve_event e
    self.e = e
    self.env = e.env
    if e.request.post?
      handle e.params
    end
  end

  def handle data
    if @success != nil
      raise 'Already handled!'
    end
    recieve(data)
    if valid?
      on_success
      @success = true
    else
      on_fail
      @success = false
    end
  end

  def flash?
    if session['flash'] && (session['flash']['class'] == self.class)
      @flash ||= session['flash']
      session['flash'] = nil
      return true
    end
  end

  def flash_kind
    @flash['kind']
  end

  def session
    raise "No env set to #{self.class}" unless env
    env['rack.session'] ||= {}
  end

  def flash message = nil, kind = 'good'
    kind += 'Flash'
    if message == nil
      if @flash || flash?
        return @flash['message']
      else
        return nil
      end
    else
      session['flash'] = {
        'class' => self.class,
        'message' => message,
        'kind' => kind
      }
    end
  end

  def recieve data
    super(self.class.tranform_post data)
  end

  def self.tranform_post post
    transformed = {}
    post.each { |k, v|
      next if k == ''
      k = k.split('[')
      name = k.shift
      name.tr! '][', ''
      if k.length == 0
        val = v
      else
        val = tranform_post k.join('[') => v
      end
      if transformed[name].kind_of? Hash
        transformed[name] =  merge(transformed[name], val)
      else
        transformed[name] = val
      end
    }
    transformed
  end

  def self.merge a, b
    a.merge(b) { |k, old, new|
      if old.kind_of? Hash
        merge(old, new)
      else
        new
      end
    }
  end

  def dump
    data = super()
    data.delete('a')
    data
  end

  def valid?
    true
  end

  def on_fail
    raise 'failed'
  end



  class Test < FwTest

    def test_form_composition
      form = Form.new
      input = InputText.new(:name => 'login')
      form << input
      assert form.fields.include? input
    end

    def test_field_fetch
      form = Form.new
      input = InputText.new(:name => 'login')
      form << input
      assert_equal input, form.field(:login)
    end

    def test_field_raise_when_no_such_field
      assert_raise(RuntimeError) { Form.new.field(:no_such_field) }
    end

    def test_render_field
      form = Form.new
      input = InputText.new(:name => 'login')
      form << input
      assert_equal input.to_s, form.render(:login)
    end

    def test_dump_makes_hash_out_of_names_and_dumps_of_fields
      form = Form.new
      form << InputText.new(:name => 'color', :value => 'blue')
      assert_equal('blue', form.dump['color'])
    end

    class MyTestForm < Form
      def on_success; end
    end

    def test_raise_when_executing_handle_twice_on_one_form
      form = MyTestForm.new
      form.handle({})
      assert_raise(RuntimeError) {
        form.handle({})
      }
    end

    def test_remove_field
      form = Form.new
      input = InputText.new(:name => 'login')
      form << input
      form.remove input
      assert !form.fields.include?(input)
    end

    def test_tranform_post_transforms_simple_nested_names
      assert_equal(
        {'user' => {'name' => 'michal'}},
        Form.tranform_post('user[name]' => 'michal')
      )
    end

    def test_tranform_post_transforms_sibling_names
      assert_equal(
        {'user' => {'name' => 'michal', 'login' => 'han345'}},
        Form.tranform_post('user[name]' => 'michal', 'user[login]' => 'han345')
      )
    end


    def test_tranform_post_transforms_deeply_nested_name
      assert_equal(
        {'user' => {'name' => { 'first' => 'michal'}}},
        Form.tranform_post('user[name][first]' => 'michal')
      )
    end

    def test_tranform_post_transforms_deeply_nested_siblings
      assert_equal(
        {'user' => {'name' => { 'first' => 'michal', 'last' => 'hantl'}}},
        Form.tranform_post('user[name][first]' => 'michal', 'user[name][last]' => 'hantl')
      )
    end


    def test_tranform_post_transforms_even_deeper_nested_siblings
      assert_equal(
        {'form' => {'user' => {'name' => { 'first' => 'michal', 'last' => 'hantl'}}}},
        Form.tranform_post('form[user][name][first]' => 'michal', 'form[user][name][last]' => 'hantl')
      )
    end
  end


end
